Step 5: BookmarkDAO Tests

Let’s test the Bookmark DAO. Create a subfolder data in the tests folder. Next, create a file BookmarkDAO.test.js in the data subfolder with the following content:

import { describe, beforeEach, expect, it } from "vitest";
import BookmarkDAO from "../../src/data/BookmarkDAO";

describe("Test BookmarkDAO", () => {
  let bookmarkDao;

  beforeEach(() => {
    bookmarkDao = new BookmarkDAO();
  });

  it("test constructor()", () => {
    expect(bookmarkDao.bookmarks.length).toBe(0);
  });
});

Notice you can use the function describe(name, fn) in each test file to create a suite that groups together several related tests.

The function it is an alias to test, and it defines a set of related expectations. It receives the test name and a function that holds the expectations to test. The describe-it convention originated with the Ruby testing library RSpec.

The beforeEach is an example of setup and teardown methods. In Vitest, there are several different setup and teardown methods, namely:

  • beforeAll — called once before all tests.
  • beforeEach — called before each of these tests (before every test function).
  • afterEach — called after each of these tests (after every test function).
  • afterAll — called once after all tests.

Let’s add a beforeAll operation to create several fake bookmarks. Moreover, we will add placeholders for more tests.

import { beforeAll, beforeEach, describe, expect, it } from "vitest";
import BookmarkDAO from "../../src/data/BookmarkDAO";
import { faker } from "@faker-js/faker";
import Bookmark from "../../src/model/Bookmark";

describe("Test BookmarkDAO", () => {
  const numBookmarks = 5;
  let bookmarks;
  let bookmarkDao;

  beforeAll(() => {
    bookmarks = [];
    for (let index = 0; index < numBookmarks; index++) {
      bookmarks.push(
        new Bookmark(faker.lorem.sentence(), faker.internet.url())
      );
    }
  });

  beforeEach(() => {
    bookmarkDao = new BookmarkDAO();
  });

  it("test constructor()", () => {
    expect(bookmarkDao.bookmarks.length).toBe(0);
  });

  it("test create()", () => {

  });

  it("test readAll()", () => {

  });

  it("test read() given valid ID", () => {

  });

  it("test read() given invalid ID", () => {

  });

  it("test update() given valid ID", () => {

  });

  it("test update() given invalid ID", () => {

  });

  it("test delete() given valid ID", () => {

  });

  it("test delete() given invalid ID", () => {

  });
});

Please take a moment and implement the tests:

import { beforeAll, beforeEach, describe, expect, it } from "vitest";
import BookmarkDAO from "../../src/data/BookmarkDAO";
import { faker } from "@faker-js/faker";
import Bookmark from "../../src/model/Bookmark";

describe("Test BookmarkDAO", () => {
  const numBookmarks = 5;
  let bookmarks;
  let bookmarkDao;

  beforeAll(() => {
    bookmarks = [];
    for (let index = 0; index < numBookmarks; index++) {
      bookmarks.push(
        new Bookmark(faker.lorem.sentence(), faker.internet.url())
      );
    }
  });

  beforeEach(() => {
    bookmarkDao = new BookmarkDAO();
  });

  it("test constructor()", () => {
    expect(bookmarkDao.bookmarks.length).toBe(0);
  });

  it("test create()", () => {
    const title = faker.lorem.sentence();
    const url = faker.internet.url();
    const bookmark = bookmarkDao.create({ title, url });
    expect(bookmarkDao.bookmarks.length).toBe(1);
    expect(bookmark.title).toBe(title);
    expect(bookmark.url).toBe(url);
    expect(bookmark.id).toBeDefined();
    expect(bookmarkDao.bookmarks[0]).toMatchObject(bookmark);
  });

  it("test readAll()", () => {
    bookmarkDao.bookmarks = bookmarks;
    expect(bookmarkDao.readAll().length).toBe(bookmarks.length);
  });

  it("test read() given valid ID", () => {
    bookmarkDao.bookmarks = bookmarks;
    const bookmark = bookmarks[0];
    expect(bookmarkDao.read(bookmark.id)).toMatchObject(bookmark);
  });

  it("test read() given invalid ID", () => {
    bookmarkDao.bookmarks = bookmarks;
    expect(bookmarkDao.read("invalid_id")).toBeUndefined();
  });

  it("test update() given valid ID", () => {
    bookmarkDao.bookmarks = bookmarks;
    const bookmark = bookmarks[0];
    expect(
      bookmarkDao.update({
        id: bookmark.id,
        title: "updated title",
        url: "update url",
      })
    ).toMatchObject({
      id: bookmark.id,
      title: "updated title",
      url: "update url",
    });
  });

  it("test update() given invalid ID", () => {
    bookmarkDao.bookmarks = bookmarks;
    expect(bookmarkDao.update({ id: "invalid_id" })).toBeUndefined();
  });

  it("test delete() given valid ID", () => {
    bookmarkDao.bookmarks = bookmarks;
    const toDelete = bookmarks[0];
    const bookmark = bookmarkDao.delete(toDelete.id);
    expect(toDelete).toMatchObject(bookmark);
    expect(bookmarkDao.bookmarks.length).toBe(numBookmarks - 1);
  });

  it("test delete() given invalid ID", () => {
    bookmarkDao.bookmarks = bookmarks;
    const bookmark = bookmarkDao.delete("invalid_id");
    expect(bookmark).toBeUndefined();
    expect(bookmarkDao.bookmarks.length).toBe(numBookmarks);
  });
});

Run the tests and notice one is failing!

Untitled

We will debug the app in the next step. For now, save and commit the changes.